package math.geom2d;

import math.base.CCS2d;
import math.base.Coord2d;
import math.base.Point2d;
import math.base.Vector2d;
import math.geomUtils.CurveType;

/**
 * @author Saga
 *
 */
public class Hyperbola2d extends ConicalCurve2d {
    public Hyperbola2d(final CCS2d _pos, final double _majorRadius, final double _monirRadius) {

    }

    @Override
    public final CurveType getCurveType() {
        return CurveType.HYPERBOLA;
    }

    @Override
    public final void reverse() {
        this.pos.yReverse();
    }

    @Override
    public final Curve2d reversed() {
        return new Hyperbola2d(this.pos.yReversed(), this.majorRadius, this.minorRadius);
    }

    @Override
    public final boolean isPeriodic() {
        return false;
    }

    @Override
    public final double getPeriod() {
        throw new ArithmeticException("");
    }

    @Override
    public final double getFirstParameter() {
        return Double.NEGATIVE_INFINITY;
    }

    @Override
    public final double getLastParameter() {
        return Double.POSITIVE_INFINITY;
    }

    @Override
    public final Point2d calcValue(final double _param) {
        final double cosVal = Math.cos(_param) * this.majorRadius;
        final double sinVal = Math.sin(_param) * this.minorRadius;
        return this.pos.getOrigin().added(this.pos.getDirectX().multiplied(cosVal)).added(
                this.pos.getDirectY().multiplied(sinVal));
    }

    @Override
    public final Vector2d calcDerivative(final double _param) {
        final double coshVal = Math.cosh(_param);
        final double sinhVal = Math.sinh(_param);

        return this.pos.getDirectX().multiplied(sinhVal * this.majorRadius)
                .added(this.pos.getDirectY().multiplied(coshVal * this.minorRadius));
    }

    @Override
    public final Vector2d calcDerivativeN(final double _param, final int _order) {
        if (_order < 1) {
            throw new ArithmeticException("");
        }

        final double coshVal = Math.cosh(_param);
        final double sinhVal = Math.sinh(_param);

        if (_order % 2 == 0) {
            return this.pos.getDirectX().multiplied(coshVal * this.majorRadius)
                    .added(this.pos.getDirectY().multiplied(sinhVal * this.minorRadius));
        } else {
            return this.pos.getDirectX().multiplied(sinhVal * this.majorRadius)
                    .added(this.pos.getDirectY().multiplied(coshVal * this.minorRadius));
        }
    }

    @Override
    public final void calcValueAndDerivative1(final double _param, final Point2d _pt,
            final Vector2d _der1) {
        final double coshVal = Math.cosh(_param);
        final double sinhVal = Math.sinh(_param);

        _pt.setCoord(this.pos.getOrigin().getCoord()
                .added(this.pos.getDirectX().getCoord().multiplied(coshVal * this.majorRadius)
                        .added(this.pos.getDirectY().getCoord()
                                .multiplied(sinhVal * this.minorRadius))));
        _der1.setCoord(this.pos.getDirectX().getCoord().multiplied(sinhVal * this.majorRadius)
                .added(this.pos.getDirectY().getCoord().multiplied(coshVal * this.minorRadius)));
    }

    @Override
    public final void calcValueAndDerivative2(final double _param, final Point2d _pt,
            final Vector2d _der1, final Vector2d _der2) {
        final double coshVal = Math.cosh(_param);
        final double sinhVal = Math.sinh(_param);

        final Coord2d coord = this.pos.getDirectX().getCoord().multiplied(
                coshVal * this.majorRadius).added(
                this.pos.getDirectY().getCoord().multiplied(sinhVal * this.minorRadius));
        final Coord2d derCoord = this.pos.getDirectX().getCoord().multiplied(
                sinhVal * this.majorRadius).added(
                this.pos.getDirectY().getCoord().multiplied(coshVal * this.minorRadius));

        _pt.setCoord(this.pos.getOrigin().getCoord().added(coord));
        _der1.setCoord(derCoord);
        _der2.setCoord(coord);
    }

    @Override
    public final void calcValueAndDerivative3(final double _param, final Point2d _pt,
            final Vector2d _der1, final Vector2d _der2, final Vector2d _der3) {
        final double coshVal = Math.cosh(_param);
        final double sinhVal = Math.sinh(_param);

        final Coord2d coord = this.pos.getDirectX().getCoord().multiplied(
                coshVal * this.majorRadius).added(
                this.pos.getDirectY().getCoord().multiplied(sinhVal * this.minorRadius));
        final Coord2d derCoord = this.pos.getDirectX().getCoord().multiplied(
                sinhVal * this.majorRadius).added(
                this.pos.getDirectY().getCoord().multiplied(coshVal * this.minorRadius));

        _pt.setCoord(this.pos.getOrigin().getCoord().added(coord));
        _der1.setCoord(derCoord);
        _der2.setCoord(coord);
        _der3.setCoord(derCoord);
    }

    @Override
    public final Hyperbola2d clone() {
        return new Hyperbola2d(this.pos.clone(), this.majorRadius, this.minorRadius);
    }

    private double majorRadius;
    private double minorRadius;
}
